<template>
  <div class="m-formitem">
    <FormModel
      ref="formRef"
      :model="form"
      :rules="rulesObj"
      :style="{ ...formStyle }"
    >
      <Row style="overflow: hidden; vertical-align: top">
        <template v-for="item in formData">
          <Col
            v-if="!item.exclude"
            v-bind="{ ...getCol(item) }"
            :key="item.field"
            :class="item.class"
          >
            <Item
              :name="item.field"
              :extra="item.extra"
              :prop="item.field"
              v-bind="{
                ...getBaseProps(item),
              }"
            >
              <slot
                v-if="typeof item.component === 'string'"
                :name="item.component"
              ></slot>
              <component
                v-else-if="isComponent(item.component)"
                :is="isComponent(item.component)"
                v-model="form[item.field]"
                v-bind="{ ...item.component.props }"
              >
                <!-- Select Option 插槽 -->
                <template #option="{ value: val, label, icon }">
                  <span role="img" :aria-label="val">{{ icon }}</span>
                  &nbsp;&nbsp;{{ label }}
                </template>
              </component>
              <div v-else>{{ item.component }}</div>
            </Item>
          </Col>
        </template>
      </Row>
    </FormModel>
  </div>
</template>
<script>
import { FormModel, Row, Col } from "ant-design-vue";
import getComponent from "./getComponent";
const { Item } = FormModel;

export default {
  name: "m-formitem",
  props: ["formData", "formStyle"],
  components: { FormModel, Item, Row, Col },
  data() {
    return {
      form: {},
    };
  },
  mounted() {
    this.form = this.initValueObj;
  },
  computed: {
    rulesObj() {
      let obj = JSON.parse(JSON.stringify({}));
      this.formData?.forEach((item) => {
        if (item && item.field && !item.exclude) {
          const { field, options: { rules = [] } = {} } = item;
          obj[field] = rules;
        }
      });
      return obj;
    },
    initValueObj() {
      let obj = JSON.parse(JSON.stringify({}));
      this.formData?.forEach((item) => {
        if (item && item.field && !item.exclude) {
          const { field, options: { initialValue } = {} } = item;
          obj[field] = initialValue;
        }
      });
      return obj;
    },
  },
  watch: {
    formData(val) {
      val?.forEach((item) => {
        const { field, component, options: { initialValue } = {} } = item;
        if (typeof component === "string") {
          this.form[field] = initialValue;
        }
      });
    },
  },
  methods: {
    isComponent(component) {
      return getComponent(component);
    },
    getCol({ col, width, style: itemStyle }) {
      if (width) {
        return {
          style: {
            float: "left",
            verticalAlign: "top",
            display: "inline-block",
            ...itemStyle,
            width,
          },
        };
      }
      if (typeof col === "number") {
        return { span: col };
      }
      if (Array.isArray(col)) {
        return { sm: col[0], xs: col[0], md: col[0], lg: col[1], xl: col[2] };
      }
      return { span: 24 };
    },
    getBaseProps(item) {
      return {
        colon: item.colon,
        label: item.label,
        ...item.layout,
        ...item.otherProps,
      };
    },
    validate() {
      return new Promise((resolve) => {
        this.$refs.formRef.validate((valid) => {
          if (valid) {
            resolve(this.form);
          } else {
            resolve(null);
          }
        });
      });
    },
    reset() {
      this.$refs.formRef.resetFields();
    },
  },
};
</script>
<style scoped lang="less">
.m-formitem {
  /deep/.ant-form {
    .ant-form-item-label {
      & > label {
        color: #666;
        line-height: 20px;
        font-size: 12px;
        font-weight: 400;
      }
    }

    .ant-select-selector,
    .ant-form-item-control-input-content > input,
    .ant-input-affix-wrapper {
      border-radius: 0 4px 4px 0;
      font-size: 12px;

      input {
        font-size: 12px;
      }
    }

    .ant-form-item-extra {
      font-size: 12px;
      line-height: 20px;
      color: #999;
      margin-top: 4px;
    }
  }
}
.btn-group {
  margin-left: auto;
  float: right;
}
</style>
